
package cz.czu.pef.DataModelling;

import java.util.*;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.persistence.*;

import org.hibernate.annotations.Index;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cz.czu.pef.DataModelling.utils.Lazy;

@Entity
@Table(name="ADDRESSES")
@Inheritance(strategy=InheritanceType.JOINED)
@ManagedBean(name="address")
@ViewScoped
@Component
@Scope(value="prototype")
public class Address extends IdPersistenceObject
{
	private static final long serialVersionUID = -2721363759656070163L;
	private String city;

	@Index(name="IDX_ADDRESS_COUNTRY")
	private String country;
	@Index(name="IDX_ADDRESS_STREETNAME")
	private String streetName;
	@Index(name="IDX_ADDRESS_ZIP")
	private String zip;

	@OneToMany(fetch=FetchType.LAZY, targetEntity=Company.class, mappedBy="baseAddress") // no cascade!
	//@OnDelete(action=OnDeleteAction.NO_ACTION)
	private Set<Company> companies;

	@ManyToMany(fetch=FetchType.LAZY, targetEntity=Company.class, mappedBy="branchAddresses") // no cascade!
	//@OnDelete(action=OnDeleteAction.NO_ACTION)
	private Set<Company> branchCompanies;

	@OneToMany(fetch=FetchType.LAZY, targetEntity=Person.class, mappedBy="address") // no cascade!
	//@OnDelete(action=OnDeleteAction.NO_ACTION)
	private Set<Person> persons;

	protected Address()
	{
		super();
	}

	public Address(String streetName, String city, String country, String zip)
	{
		setStreetName(streetName);
		setCity(city);
		setCountry(country);
		setZip(zip);
	}

	public String getCity()
	{
		return city;
	}


	public String getCountry()
	{
		return country;
	}

	public String getStreetName()
	{
		return streetName;
	}

	public String getZip()
	{
		return zip;
	}

	public void setCity(final String city)
	{
		this.city = city;
	}


	public void setStreetName(String streetName)
	{
		this.streetName = streetName;
	}

	public void setZip(final String zip)
	{
		this.zip = zip;
	}

	
	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public Set<Person> getPersons()
	{
		return persons;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public List<Person> getPersonsAsList()
	{
		return new ArrayList<Person>(getPersons());
	}

	public void setPersons(Set<Person> persons)
	{
		this.persons = persons;
	}

	
	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public Set<Company> getCompanies()
	{
		return companies;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public List<Company> getCompaniesAsList()
	{
		return new ArrayList<Company>(getCompanies());
	}

	
	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public Set<Company> getBranchCompanies()
	{
		return branchCompanies;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public List<Company> getBranchCompaniesAsList()
	{
		return new ArrayList<Company>(getBranchCompanies());
	}

	
	public void setCountry(String country)
	{
		this.country = country;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	@Override
	public String toString()
	{
		StringBuilder builder = new StringBuilder();
		builder.append("Address [city=");
		builder.append(city);
		builder.append(", country=");
		builder.append(country);
		builder.append(", streetName=");
		builder.append(streetName);
		builder.append(", zip=");
		builder.append(zip);
		builder.append(", toString()=");
		builder.append(super.toString());
		builder.append("]");
		return builder.toString();
	}


	/**
	 * Address can be deleted only when there is no reference to it.
	 */
	@Override
	public boolean canBeRemoved()
	{
		boolean removable = (getCompanies().size() == 0) && (getBranchCompanies().size() == 0) && (getPersons().size() == 0);
		return removable;
	}

}
